package cn._2dland.util;

import java.io.ByteArrayOutputStream;

/**
 * Base64工具类
 * 
 * @author deadblue
 */
public class Base64 {

	/** Base64编码用字符串 */
	private static final String BASE64_CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

	/**
	 * Base64编码
	 * 
	 * @param datas
	 * @return
	 */
	public static String encode(byte[] datas) {
		StringBuffer buf = new StringBuffer();

		// 中间变量
		byte b1, b2, b3;
		int e1, e2, e3, e4;
		
		for(int i = 0; i < datas.length; ) {
			// 读取第一个字节，编码
			b1 = datas[i++];
			e1 = (b1 & 0xfc) >> 2;
			e2 = (b1 & 0x03) << 4;
			e3 = 64;
			e4 = 64;

			// 第二个字节
			if(i < datas.length) {
				b2 = datas[i++];

				e2 |= (b2 & 0xf0) >> 4;
				e3 = (b2 & 0x0f) << 2;
			}

			// 第三个字节
			if(i < datas.length) {
				b3 = datas[i++];

				e3 |= (b3 & 0xc0) >> 6;
				e4 = b3 & 0x3f;
			}

			// 将结果放入缓冲区
			buf.append(BASE64_CHAR.charAt(e1))
				.append(BASE64_CHAR.charAt(e2))
				.append(BASE64_CHAR.charAt(e3))
				.append(BASE64_CHAR.charAt(e4));
		}
		
		return buf.toString();
	}

	/**
	 * Base64解码
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] decode(String str) {

		byte[] result = null;
		
		try {
			if(str == null || str.length() % 4 != 0)
				throw new InvalidBase64StringException();

			int c1, c2, c3, c4;
			ByteArrayOutputStream buf = new ByteArrayOutputStream();

			for(int i = 0; i < str.length(); i += 4) {
				c1 = BASE64_CHAR.indexOf(str.charAt(i));
				if(c1 < 0) throw new InvalidBase64StringException();
				c2 = BASE64_CHAR.indexOf(str.charAt(i + 1));
				if(c2 < 0) throw new InvalidBase64StringException();
				c3 = BASE64_CHAR.indexOf(str.charAt(i + 2));
				if(c3 < 0) throw new InvalidBase64StringException();
				c4 = BASE64_CHAR.indexOf(str.charAt(i + 3));
				if(c4 < 0) throw new InvalidBase64StringException();

				int b = (c1 << 2) | (c2 >> 4);
				buf.write(b);
				if(c3 < 64) {
					b = ((c2 & 0x0f) << 4) | (c3 >> 2);
					buf.write(b);
				}
				if(c4 < 64) {
					b = ((c3 & 0x03) << 6) | c4;
					buf.write(b);
				}
			}

			// 返回结果
			buf.close();
			result = buf.toByteArray();
		} catch (Exception e) {
			result = null;
			e.printStackTrace();
		}

		return result;
	}

}

class InvalidBase64StringException extends Exception {

	private static final long serialVersionUID = 1L;
	
	public InvalidBase64StringException() {
		super("Invalid base64 string!");
	}

}